﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TestGame
{
    public class Sprite : IComparable<Sprite>
    {
        // position gets restricted into the map, unless we have no map.
        private Vector2 _position;
        public Vector2 Position
        {
            set
            {
                if (currentMap == null)
                {
                    _position = value;
                    return;
                }

                _position.X = MathHelper.Clamp(value.X, 0, currentMap.totalWidth - this.Size.Width);
                _position.Y = MathHelper.Clamp(value.Y, 0, currentMap.totalHeight - this.Size.Height);
            }
            get { return _position; }
        }
        public Texture2D Texture { get; private set; }
        public String AssetName { get; private set; }
        public Rectangle Size { get; private set; }

        // layer gets clamped between 0 and 1024.. just 'cause, I guess.
        private float _layer = 10;
        public float Layer
        {
            get { return _layer; }
            set
            {
                _layer = MathHelper.Clamp((float)value, 0f, 1024f);
            }
        }

        public Map currentMap { get; set; }

        // scale resets the size of the texture, although it's almost purely aesthetic..
        // this is mostly here so the class can be reused
        private float _scale = 1f;
        public float Scale
        {
            get { return _scale; }
            set
            {
                _scale = value;
                Size = new Rectangle(0, 0, (int)(Texture.Width * Scale), (int)(Texture.Height * Scale));
            }
        }
        protected const int MOVE_SPEED = 160;

        // different states a sprite can represent
        public enum State
        {
            Walking,
            Background
        }

        public State CurrentState = State.Walking;

        protected Vector2 mDirection = Vector2.Zero;
        protected Vector2 mSpeed = Vector2.Zero;

        // some basic constructors
        public Sprite() : this(0, 0) { }

        public Sprite(int x, int y) : this(x, y, "sprite") { }

        public Sprite(int x, int y, string asset) : this(x, y, asset, Game.GLOBAL_SIZE) { }

        public Sprite(int x, int y, string asset, float scale)
        {
            Position = new Vector2(x, y);
            AssetName = asset;
            LoadContent(SpriteManager.manager);
            SpriteManager.AddSprite(this);
            Scale = scale;
        }

        // check if mouseHit (x,y) is where the sprite object is
        public bool Intersect(Vector2 mouseHit)
        {
            int x = Game.TILE_HEIGHT;

            // we do something special for HUD objects
            if (GetType().Equals(typeof(HUD)))
            {
                return ((int)(mouseHit.X / x) == (int)(Position.X / x) &&
                        (int)(mouseHit.Y / x) == (int)(Position.Y / x));
            }
            return ((int)((mouseHit.X + Game.camera.Position.X) / x)
                        == (int)(Position.X / x) &&
                    (int)((mouseHit.Y + Game.camera.Position.Y) / x)
                        == (int)(Position.Y / x)
                    );
        }

        public virtual void Update(GameTime gametime) { }

        public virtual void Clicked(SpriteBatch batch, GraphicsDevice graphics, Sprite clicked) { }

        public void LoadContent(ContentManager theContentManager)
        {
            Texture = theContentManager.Load<Texture2D>(AssetName);
        }

        public void Draw(SpriteBatch theSpriteBatch)
        {
            theSpriteBatch.Draw(Texture, Position,
                           new Rectangle(0, 0, Texture.Width, Texture.Height),
                           Color.White, 0.0f, Vector2.Zero, Scale, SpriteEffects.None, 0);
        }

        public int CompareTo(Sprite s)
        {
            return (int)(Layer - s.Layer);
        }
    }
}